/*!
 * \file 8583.c
 *
 * \brief 共通定义
 *
 * All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.\n
 * 共通使用的宏和结构体
 *
 * \version 1.0
 * \author jikw
 * \date 2015/09/14
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "frbyte_buffer.h"
#include "frreport_comm.h"
#include "frct_comm.h"
#include "8583.h"
#include "frservice_comm.h"
#include "config.h"

#define  ISO8583_REQ_MESSAGE_TYPE  "request.ISO8583.message_type"
#define  ISO8583_RESP_MESSAGE_TYPE  "response.ISO8583.message_type"
#define  ISO8583_TRANSACTION_TITLE  "transaction.title"
#define  ISO8583_LENGH  129 //消息类型+128个域

extern void *g_p_apm_context;

typedef struct __st_L7session_8583_private
{
    unsigned long ul_seq;                             //序列号，1次req和response时，使用同一个序列号
    L4_transaction st_l4_trans;                       //数据
    Frreport_body_data *p_st_body_data_req;
    Frreport_body_data *p_st_body_data_resp;
    Frlist_header *p_lst_comm;
    Frlist_header *p_lst_req;
    Frbyte_Packet *p_req_packet;
    int i_req_remain_len;
    Frbyte_Packet *p_resp_packet;
    int i_resp_remain_len;
}L7session_8583_private;

typedef struct DATA8583
{
char *data_value;        //存各域值数据
} DATA8583;

typedef struct ISO8583
{
const char  *data_name;  //域名
int   length;            //数据域长度
int   variable_flag;     //是否变长标志0：否 2：2位变长, 3：3位变长
int   datatyp;           //0 -- B(二进制), 1 -- N（BCD码）, 2 -- Z（ASC）, 3 -- AN（ASC）, 4 -- ANS, 5 -- UNKNOW
} ISO8583;

ISO8583 Tbl8583[128] =
{
/* FLD 01 */ {"BIT MAP,EXTENDED", 8, 0, 0},
/* FLD 02 */ {"PRIMARY ACCOUNT NUMBER", 22, 2, 1},
/* FLD 03 */ {"PROCESSING CODE", 6, 0, 1},
/* FLD 04 */ {"AMOUNT, TRANSACTION", 12, 0, 1},
/* FLD 05 */ {"NO USE", 12, 0, 5},
/* FLD 06 */ {"NO USE", 12, 0, 5},
/* FLD 07 */ {"TRANSACTION DATE AND TIME", 10, 0, 1},
/* FLD 08 */ {"NO USE", 8, 0, 5},
/* FLD 09 */ {"NO USE", 8, 0, 5},
/* FLD 10 */ {"NO USE", 8, 0, 5},
/* FLD 11 */ {"SYSTEM TRACE AUDIT NUMBER", 6, 0, 1},
/* FLD 12 */ {"TIME, LOCAL TRANSACTION", 6, 0, 1},
/* FLD 13 */ {"DATE, LOCAL TRANSACTION", 4, 0, 1},
/* FLD 14 */ {"DATE, EXPIRATION", 4, 0, 1},
/* FLD 15 */ {"DATE, SETTLEMENT", 4, 0, 1},
/* FLD 16 */ {"NO USE", 4, 0, 5},
/* FLD 17 */ {"DATE, CAPTURE", 4, 0, 1},
/* FLD 18 */ {"MERCHANT'S TYPE", 4, 0, 1},
/* FLD 19 */ {"NO USE", 3, 0, 5},
/* FLD 20 */ {"NO USE", 3, 0, 5},
/* FLD 21 */ {"NO USE", 3, 0, 5},
/* FLD 22 */ {"POINT OF SERVICE ENTRY MODE", 3, 0, 1},
/* FLD 23 */ {"NO USE", 3, 0, 5},
/* FLD 24 */ {"NO USE", 3, 0, 5},
/* FLD 25 */ {"POINT OF SERVICE CONDITION CODE", 2, 0, 1},
/* FLD 26 */ {"NO USE", 2, 0, 5},
/* FLD 27 */ {"NO USE", 1, 0, 5},
/* FLD 28 */ {"field27", 6, 0, 5},
/* FLD 29 */ {"NO USE", 8, 0, 5},
/* FLD 30 */ {"NO USE", 8, 0, 5},
/* FLD 31 */ {"NO USE", 8, 0, 5},
/* FLD 32 */ {"ACQUIRER INSTITUTION ID. CODE", 11, 2, 1},
/* FLD 33 */ {"FORWARDING INSTITUTION ID. CODE", 11, 2, 1},
/* FLD 34 */ {"NO USE", 28, 2, 5},
/* FLD 35 */ {"TRACK 2 DATA", 37, 2, 2},
/* FLD 36 */ {"TRACK 3 DATA",104, 3, 2},
/* FLD 37 */ {"RETRIEVAL REFERENCE NUMBER", 12, 0, 3},
/* FLD 38 */ {"AUTH. IDENTIFICATION RESPONSE", 6, 0, 3},
/* FLD 39 */ {"RESPONSE CODE", 2, 0, 3},
/* FLD 40 */ {"NO USE", 3, 0, 5},
/* FLD 41 */ {"CARD ACCEPTOR TERMINAL ID.", 8, 0, 4},
/* FLD 42 */ {"CARD ACCEPTOR IDENTIFICATION CODE", 15, 0, 4},
/* FLD 43 */ {"CARD ACCEPTOR NAME LOCATION", 40, 0, 4},
/* FLD 44 */ {"ADDITIONAL RESPONSE DATA", 25, 2, 4},
/* FLD 45 */ {"NO USE", 76, 2, 5},
/* FLD 46 */ {"NO USE", 999, 3, 5},
/* FLD 47 */ {"field47", 999, 3, 5},
/* FLD 48 */ {"ADDITIONAL DATA --- PRIVATE", 999, 3, 4},
/* FLD 49 */ {"CURRENCY CODE,TRANSACTION", 3, 0, 3},
/* FLD 50 */ {"CURRENCY CODE,SETTLEMENT", 3, 0, 3},
/* FLD 51 */ {"NO USE", 3, 0, 5},
/* FLD 52 */ {"PERSONAL IDENTIFICATION NUMBER DATA", 8, 0, 0},
/* FLD 53 */ {"SECURITY RELATED CONTROL INformATION", 16, 0, 3},
/* FLD 54 */ {"ADDITIONAL AMOUNTS",120, 3, 4},
/* FLD 55 */ {"NO USE", 999, 3, 5},
/* FLD 56 */ {"NO USE", 999, 3, 5},
/* FLD 57 */ {"NO USE", 999, 3, 5},
/* FLD 58 */ {"NO USE", 999, 3, 5},
/* FLD 59 */ {"NO USE", 999, 3, 5},
/* FLD 60 */ {"NO USE", 5, 3, 5},
/* FLD 61 */ {"NO USE", 999, 3, 5},
/* FLD 62 */ {"NO USE", 11, 3, 5},
/* FLD 63 */ {"NO USE", 11, 3, 5},
/* FLD 64 */ {"MESSAGE AUTHENTICATION CODE FIELD", 8, 0, 0},
/* FLD 65 */ {"NO USE", 999, 3, 5},
/* FLD 66 */ {"NO USE", 1, 0, 5},
/* FLD 67 */ {"NO USE", 999, 3, 5},
/* FLD 68 */ {"NO USE", 999, 3, 5},
/* FLD 69 */ {"NO USE", 999, 3, 5},
/* FLD 70 */ {"SYSTEM MANAGEMENT INformATION CODE", 3, 0, 1},
/* FLD 71 */ {"NO USE", 999, 3, 5},
/* FLD 72 */ {"NO USE", 999, 3, 5},
/* FLD 73 */ {"NO USE", 6, 0, 5},
/* FLD 74 */ {"NUMBER OF CREDITS", 10, 0, 1},
/* FLD 75 */ {"REVERSAL NUMBER OF CREDITS", 10, 0, 1},
/* FLD 76 */ {"NUMBER OF DEBITS", 10, 0, 1},
/* FLD 77 */ {"REVERSAL NUMBER OF DEBITS", 10, 0, 1},
/* FLD 78 */ {"NUMBER OF TRANSFER", 10, 0, 1},
/* FLD 79 */ {"REVERSAL NUMBER OF TRANSFER", 10, 0, 1},
/* FLD 80 */ {"NUMBER OF INQUIRS", 10, 0, 1},
/* FLD 81 */ {"AUTHORIZATION NUMBER", 10, 0, 1},
/* FLD 82 */ {"NO USE", 12, 0, 5},
/* FLD 83 */ {"CREDITS,TRANSCATION FEEAMOUNT", 12, 0, 1},
/* FLD 84 */ {"NO USE", 12, 0, 5},
/* FLD 85 */ {"DEBITS,TRANSCATION FEEAMOUNT", 12, 0, 1},
/* FLD 86 */ {"AMOUNT OF CREDITS", 16, 0, 1},
/* FLD 87 */ {"REVERSAL AMOUNT OF CREDITS", 16, 0, 1},
/* FLD 88 */ {"AMOUNT OF DEBITS", 16, 0, 1},
/* FLD 89 */ {"REVERSAL AMOUNT OF DEBITS", 16, 0, 1},
/* FLD 90 */ {"ORIGINAL DATA ELEMENTS", 42, 0, 1},
/* FLD 91 */ {"FILE UPDATE CODE", 1, 0, 3},
/* FLD 92 */ {"NO USE", 999, 3, 5},
/* FLD 93 */ {"NO USE", 999, 3, 5},
/* FLD 94 */ {"SERVICE INDICATOR", 7, 0, 3},
/* FLD 95 */ {"REPLACEMENT AMOUNTS", 42, 0, 1},
/* FLD 96 */ {"NO USE", 8, 0, 5},
/* FLD 97 */ {"AMOUNT OF NET SETTLEMENT", 16, 0, 1},
/* FLD 98 */ {"NO USE", 999, 3, 5},
/* FLD 99 */ {"SETTLEMENT INSTITUTION ID", 11, 2, 1},
/* FLD 100 */ {"RECVEING INSTITUTION ID", 11, 2, 1},
/* FLD 101 */ {"FILENAME", 17, 2, 4},
/* FLD 102 */ {"ACCOUNT IDENTIFICATION1", 28, 2, 4},
/* FLD 103 */ {"ACCOUNT IDENTIFICATION2", 28, 2, 4},
/* FLD 104 */ {"NO USE", 999, 3, 5},
/* FLD 105 */ {"NO USE", 999, 3, 5},
/* FLD 106 */ {"NO USE", 999, 3, 5},
/* FLD 107 */ {"NO USE", 999, 3, 5},
/* FLD 108 */ {"NO USE", 999, 3, 5},
/* FLD 109 */ {"NO USE", 999, 3, 5},
/* FLD 110 */ {"NO USE", 999, 3, 5},
/* FLD 111 */ {"NO USE", 999, 3, 5},
/* FLD 112 */ {"NO USE", 999, 3, 5},
/* FLD 113 */ {"NO USE", 999, 3, 5},
/* FLD 114 */ {"NO USE", 999, 3, 5},
/* FLD 115 */ {"NO USE", 999, 3, 5},
/* FLD 116 */ {"NO USE", 999, 3, 5},
/* FLD 117 */ {"NO USE", 999, 3, 5},
/* FLD 118 */ {"NO USE", 999, 3, 5},
/* FLD 119 */ {"NO USE", 999, 3, 5},
/* FLD 120 */ {"NO USE", 999, 3, 5},
/* FLD 121 */ {"NO USE", 999, 3, 5},
/* FLD 122 */ {"NO USE", 999, 3, 5},
/* FLD 123 */ {"NEW PIN DATA", 8, 3, 0},
/* FLD 124 */ {"NO USE", 999, 3, 5},
/* FLD 125 */ {"NO USE", 999, 3, 5},
/* FLD 126 */ {"NO USE", 999, 3, 5},
/* FLD 127 */ {"NO USE", 999, 3, 5},
/* FLD 128 */ {"MESSAGE AUTHENTICATION CODE FIELD", 8, 0, 0},
};

/*!
 * 8583私有数据创建
 *
 * \param void
 *
 * \return NULL          内存分配失败\n
 *         p_st_private  内存分配成功
 *
 * \note
 *
 */
FR_STATIC L7session_8583_private* __8583_private_create(void)
{
    L7session_8583_private *p_st_private = NULL;

    p_st_private = (L7session_8583_private*)frmalloc(sizeof(L7session_8583_private));
    if (p_st_private == NULL)
        return NULL;

    memset(p_st_private, 0x00, sizeof(L7session_8583_private));
    return p_st_private;
}

/*!
 * 私有信息reset
 *
 * \param p_private_session  (8583的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
FR_STATIC int __ISO8583_session_reset(void *p_private_session)
{
    L7session_8583_private *p_st_private = (L7session_8583_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));
    }
    return FR_SUCC;
}

/*!
 * 格式转换将16进制数据转换为可见的内容
 *
 * \param p_data     (原数据)
 * \param i_len      (原数据长度)
 *
 * \return p_value    转换后数据\n
 *
 * \note 需要外部释放返回值
 *
 */
FR_STATIC char* __hex_bcd(char *p_data, int i_len)
{
    int i_count = 0;
    char *p_value = NULL;
    char hex_int[] = "0123456789abcdef";
    #define hex_int_lo(x)   hex_int[((x) & 0x0f)]
    #define hex_int_hi(x)   hex_int[((x) & 0xf0) >> 4]

    if (p_data == NULL || i_len == 0)
        return NULL;

    p_value = (char*)frmalloc(i_len*2+1);
    if (p_value == NULL)
        return NULL;

    for (i_count=0; i_count<i_len; i_count++)
    {
        p_value[i_count*2] = hex_int_hi(*(p_data+i_count));
        p_value[i_count*2+1] = hex_int_lo(*(p_data+i_count));
    }
    p_value[i_count*2] = '\0';

    return p_value;
}

/*!
 * 将16进制数据转换为数字,计算数据包长度
 *
 * \param p_data     (原数据)
 *
 * \return i_len      转换后长度\
 *
 * \note 需要外部释放返回值
 *
 */
FR_STATIC int __packet_len(char *p_data)
{
    int i_len = 0;
    int *p_i_tmp = NULL;
    char arr_tmp_len[4];

    memset(arr_tmp_len, 0x00, sizeof(arr_tmp_len));
    memcpy(arr_tmp_len + 2, p_data, 2);
    p_i_tmp = (int *)arr_tmp_len;
    i_len = ntohl(*p_i_tmp);

    return i_len;
}

/*!
 * 判断是否是8583协议
 *
 * \param p_st_conn      (输入数据信息)
 * \param p_st_packet    (输入数据)
 *
 * \return APM_L7_IS_YES  属于8583协议\n
 *         APM_L7_IS_NO   不属于8583协议
 *
 * \note
 *
 */
int ISO8583_detect(Conntrack *p_st_conn, Apm_packet *p_st_packet)
{
    int i_ret = 0;
    int i_lengh = 0;
    int i_ret_fun = 0;

    if (p_st_packet == NULL || p_st_packet->p_payload == NULL || p_st_conn==NULL || p_st_packet->ui_payload_len < 23)
        return APM_L7_IS_NO;

    //i_ret_fun = frct_get_direct_known(p_st_conn);
    //if (i_ret_fun == FR_DIRECT_UNKNOWN)
        //return APM_L7_IS_NO;

    i_lengh = __packet_len(p_st_packet->p_payload);
    //判断i_lengh+2与数据长度是否相等
    if (p_st_packet->ui_payload_len != (unsigned int)i_lengh + 2)
        goto error;
    //0220 0230 0320 0330 0500 0510 0820 0830
    //第13、14字节为消息类型：0100 0110 0200 0210 0240 0250 0400 0410 0800 0810
    switch (p_st_packet->p_payload[13])
    {
        case 0x01:
            if (p_st_packet->p_payload[14] != 0x00 && p_st_packet->p_payload[14] != 0x10)
                goto error;
            break;
        case 0x02:
            if (p_st_packet->p_payload[14] != 0x00 && p_st_packet->p_payload[14] != 0x10 &&
                p_st_packet->p_payload[14] != 0x20 && p_st_packet->p_payload[14] != 0x30 &&
                p_st_packet->p_payload[14] != 0x40 && p_st_packet->p_payload[14] != 0x50)
                goto error;
            break;
        case 0x03:
            if (p_st_packet->p_payload[14] != 0x20 && p_st_packet->p_payload[14] != 0x30)
                goto error;
            break;
        case 0x04:
            if (p_st_packet->p_payload[14] != 0x00 && p_st_packet->p_payload[14] != 0x10)
                goto error;
            break;
        case 0x05:
            if (p_st_packet->p_payload[14] != 0x00 && p_st_packet->p_payload[14] != 0x10)
                goto error;
            break;
        case 0x08:
            if (p_st_packet->p_payload[14] != 0x00 && p_st_packet->p_payload[14] != 0x10 &&
                p_st_packet->p_payload[14] != 0x20 && p_st_packet->p_payload[14] != 0x30)
                goto error;
            break;
        default:
            goto error;
    }
    i_ret_fun = frct_get_direct_known(p_st_conn);
    if ( i_ret_fun == FR_DIRECT_UNKNOWN)
        frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);

    frservice_add(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0);
    return APM_L7_IS_YES;

error:
    if (frct_get_direct_known(p_st_conn) == FR_DIRECT_UNKNOWN)
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->dst_ip, p_st_packet->dst_port);
            return APM_L7_IS_YES;
        }
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
        {
            frcap_set_cs_srv(p_st_conn, p_st_packet->src_ip, p_st_packet->src_port);
            return APM_L7_IS_YES;
        }
    }
    else
    {
        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->src_ip, p_st_packet->src_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;

        i_ret = frservice_get(g_p_apm_context, MODULE_L7PROTO, p_st_packet->dst_ip, p_st_packet->dst_port, NULL, 0, NULL);
        if (i_ret == FR_SUCC)
            return APM_L7_IS_YES;
    }
    return APM_L7_IS_NO;
}

/*!
 * req数据解析
 *
 * \param p_data          (req数据)
 * \param ui_data_len     (req数据长度)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC)   成功\n
 *         APM_L7_ANALYZE_FAIL   失败\n
 *         APM_L7_ANALYZE_TODO   数据不完整
 *
 * \note
 *
 */
FR_STATIC int __req_parse(char *p_data, unsigned int ui_data_len, L7session_8583_private *p_st_private, Frreport_body_data *p_st_body_data, Conntrack *p_st_conn)
{
    int i_count = 0;
    int i_bit = 0;
    int i_lengh = 0;
    int i_temp = 0;
    int i_tmp = 0;
    int i_bit_pos = 0;
    int i_req_len = 0;
    char arr_unuse[13];
    char arr_message_type[2];
    char arr_bit_map_16[16];
    char arr_value[1024];
    char arr_len[2];
    char arr_name[26];
    char *p_data_bcd = NULL;
    char arr_name_1[] = "request.ISO8583.fields.";
    Frbyte_Packet *p_packet = NULL;

    if (p_data == NULL || ui_data_len == 0 || p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

    memset(arr_unuse, 0x00, sizeof(arr_unuse));
    memset(arr_message_type, 0x00, sizeof(arr_message_type));
    memset(arr_bit_map_16, 0x00, sizeof(arr_bit_map_16));
    memset(arr_value, 0x00, sizeof(arr_value));
    memset(arr_len, 0x00, sizeof(arr_len));
    memset(arr_name, 0x00, sizeof(arr_name));

    DATA8583 upload[ISO8583_LENGH];
    memset(upload, 0x00, sizeof(DATA8583)*ISO8583_LENGH);

    if (p_st_private->i_req_remain_len == 0)
    {
        i_req_len = __packet_len(p_data);
        p_st_private->i_req_remain_len = i_req_len + 2 - ui_data_len;

        p_st_private->p_req_packet = bytebuff_creat();
        if (p_st_private->p_req_packet == NULL)
            goto ERROR;
    }
    else
        p_st_private->i_req_remain_len -= ui_data_len;
    p_packet = p_st_private->p_req_packet;
    if (bytebuff_add(p_packet, p_data, ui_data_len) != FR_SUCC)
        goto ERROR;
    if (p_st_private->i_req_remain_len < 0)
        goto ERROR;
    if (p_st_private->i_req_remain_len > 0)
        return APM_L7_ANALYZE_TODO;

    /*
     2字节:字节长度
     5字节：TPDU
     6字节：报文头
     2字节：消息类型
     8字节：位图
     之后为各个域的域值
    */

    //arr_unuse存放前13字节无用信息
    if (bytebuff_get_bytes(p_packet, arr_unuse, 13) == FR_FAIL)
        goto ERROR;

    //上报消息类型
    if (bytebuff_get_bytes(p_packet, arr_message_type, 2) == FR_FAIL)
        goto ERROR;
    p_data_bcd = __hex_bcd(arr_message_type, 2);
    upload[0].data_value = p_data_bcd;

    //确定位图 arr_bit_map_16为十六进制位图
    if (((*(p_data+15)) & 0x80) != 0x80)
        i_bit = 8;
    else
        i_bit = 16;
    if (bytebuff_get_bytes(p_packet, arr_bit_map_16, i_bit) == FR_FAIL)
        goto ERROR;

    for (i_count=0; i_count<i_bit*8; i_count++)
    {
        i_tmp = i_count/8;
        i_bit_pos = i_count - i_tmp*8;
        //如果该域有值
        if ((arr_bit_map_16[i_tmp]&(0x80>>i_bit_pos)) != 0)
        {
            //判断该域长度是定长还是变长
            if (Tbl8583[i_count].variable_flag == 0)
            {
                //如果数据类型是BCD码,i_temp长度取半
                if (Tbl8583[i_count].datatyp == 1)
                {
                    i_temp = (Tbl8583[i_count].length + 1) / 2;
                    if (bytebuff_get_bytes(p_packet, arr_value, i_temp) == FR_FAIL)
                        goto ERROR;
                    p_data_bcd = __hex_bcd(arr_value, i_temp);
                    //如果长度是奇数，舍最后一位
                    if ((Tbl8583[i_count].length%2) == 1)
                        *(p_data_bcd+i_temp*2-1) = '\0';
                    upload[i_count+1].data_value = p_data_bcd;
                }
                //如果数据类型是ASCII码或2进制
                else
                {
                    upload[i_count+1].data_value = (char*)frmalloc(Tbl8583[i_count].length+1);
                    if (upload[i_count+1].data_value == NULL)
                        goto ERROR;
                    memset(upload[i_count+1].data_value, 0x00, Tbl8583[i_count].length+1);
                    if (bytebuff_get_bytes(p_packet, upload[i_count+1].data_value, Tbl8583[i_count].length) == FR_FAIL)
                        goto ERROR;
                }
            }
            else if (Tbl8583[i_count].variable_flag == 2)
            {
                //变长情况（前1个字节为长度），16进制长度存进arr_len
                if (bytebuff_get_bytes(p_packet, arr_len, 1) == FR_FAIL)
                    goto ERROR;
                i_lengh = ((arr_len[0] & 0xf0)>>4)*10 + (arr_len[0] & 0x0f);
                //如果数据类型是BCD码,i_temp长度取半
                if (Tbl8583[i_count].datatyp == 1)
                {
                    i_temp = (i_lengh + 1) / 2;
                    if (bytebuff_get_bytes(p_packet, arr_value, i_temp) == FR_FAIL)
                        goto ERROR;
                    p_data_bcd = __hex_bcd(arr_value, i_temp);
                    //如果变长长度是奇数，舍最后一位
                    if ((i_lengh%2) == 1)
                        *(p_data_bcd+i_temp*2-1) = '\0';
                    upload[i_count+1].data_value = p_data_bcd;
                }
                //如果数据类型是ASCII码或2进制
                else
                {
                    upload[i_count+1].data_value = (char*)frmalloc(i_lengh+1);
                    if (upload[i_count+1].data_value == NULL)
                        goto ERROR;
                    memset(upload[i_count+1].data_value, 0x00, i_lengh+1);
                    if (bytebuff_get_bytes(p_packet, upload[i_count+1].data_value, i_lengh) == FR_FAIL)
                        goto ERROR;
                }
            }
            else if (Tbl8583[i_count].variable_flag == 3)
            {
                //变长情况（前2个字节为长度）
                if (bytebuff_get_bytes(p_packet, arr_len, 2) == FR_FAIL)
                    goto ERROR;
                i_lengh = ((arr_len[0] & 0xf0)>>4)*1000 + (arr_len[0] & 0x0f)*100 + ((arr_len[1] & 0xf0)>>4)*10 + (arr_len[1] & 0x0f);
                //如果数据类型是BCD码,i_temp长度取半
                if (Tbl8583[i_count].datatyp == 1)
                {
                    i_temp = (i_lengh + 1) / 2;
                    if (bytebuff_get_bytes(p_packet, arr_value, i_temp) == FR_FAIL)
                        goto ERROR;
                    p_data_bcd = __hex_bcd(arr_value, i_temp);
                    //如果变长长度是奇数，舍最后一位
                    if ((i_lengh%2) == 1)
                        *(p_data_bcd+i_temp*2-1) = '\0';
                    upload[i_count+1].data_value = p_data_bcd;
                }
                //如果数据类型是ASCII码或2进制
                else
                {
                    upload[i_count+1].data_value = (char*)frmalloc(i_lengh+1);
                    if (upload[i_count+1].data_value == NULL)
                        goto ERROR;
                    memset(upload[i_count+1].data_value, 0x00, i_lengh+1);
                    if (bytebuff_get_bytes(p_packet, upload[i_count+1].data_value, i_lengh) == FR_FAIL)
                        goto ERROR;
                }
            }
            else
                goto ERROR;
        }
    }

    for (i_count=0; i_count<i_bit*8+1; i_count++)
    {
        if (upload[i_count].data_value != NULL)
        {
            if (i_count==0)
            {
                if (frreport_body_l7_add_str(p_st_body_data, ISO8583_TRANSACTION_TITLE, upload[i_count].data_value) == FR_FAIL)
                    goto ERROR;
                if (frreport_body_l7_add_str(p_st_body_data, ISO8583_REQ_MESSAGE_TYPE, upload[i_count].data_value) == FR_FAIL)
                    goto ERROR;
            }
            else if (i_count==52 || i_count==64 || i_count==123 ||i_count==128)
            {
                snprintf(arr_name, sizeof(arr_name), "%s%d", arr_name_1, i_count);
                if (frreport_body_l7_add_bin(p_st_body_data, arr_name, upload[i_count].data_value, 8) == FR_FAIL)
                    goto ERROR;
            }
            else
            {
                snprintf(arr_name, sizeof(arr_name), "%s%d", arr_name_1, i_count);
                if (frreport_body_l7_add_str(p_st_body_data, arr_name, upload[i_count].data_value) == FR_FAIL)
                    goto ERROR;
            }
        }
    }

    for (i_count=0; i_count<i_bit*8+1; i_count++)
    {
        if (upload[i_count].data_value)
        {
            frfree(upload[i_count].data_value);
            upload[i_count].data_value = NULL;
        }
    }
    return APM_L7_ANALYZE_SET_REQ(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_packet)
    {
        bytebuff_free(&p_packet);
        p_st_private->p_req_packet = NULL;
    }
    for (i_count=0; i_count<ISO8583_LENGH; i_count++)
    {
        if (upload[i_count].data_value)
        {
            frfree(upload[i_count].data_value);
            upload[i_count].data_value = NULL;
        }
    }
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * resp数据解析
 *
 * \param p_data          (resp数据)
 * \param ui_data_len     (resp数据长度)
 * \param p_st_private    (私有数据)
 * \param p_st_body_data
 * \param p_st_conn       (入力链接信息)
 *
 * \return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC)   成功\n
 *         APM_L7_ANALYZE_FAIL   失败\n
 *         APM_L7_ANALYZE_TODO   数据不完整
 *
 * \note
 *
 */
FR_STATIC int __resp_parse(char *p_data, unsigned int ui_data_len, L7session_8583_private *p_st_private, Frreport_body_data *p_st_body_data, Conntrack *p_st_conn)
{
    int i_count = 0;
    int i_bit = 0;
    int i_lengh = 0;
    int i_temp = 0;
    int i_tmp = 0;
    int i_bit_pos = 0;
    int i_resp_len = 0;
    char arr_unuse[13];
    char arr_message_type[2];
    char arr_bit_map_16[16];
    char arr_value[1024];
    char arr_len[2];
    char arr_name[27];
    char *p_data_bcd = NULL;
    char arr_name_1[] = "response.ISO8583.fields.";
    Frbyte_Packet *p_packet = NULL;

    if (p_data == NULL || ui_data_len == 0 || p_st_private == NULL || p_st_body_data == NULL || p_st_conn == NULL)
        return APM_L7_ANALYZE_FAIL;

    memset(arr_unuse, 0x00, sizeof(arr_unuse));
    memset(arr_message_type, 0x00, sizeof(arr_message_type));
    memset(arr_bit_map_16, 0x00, sizeof(arr_bit_map_16));
    memset(arr_value, 0x00, sizeof(arr_value));
    memset(arr_len, 0x00, sizeof(arr_len));
    memset(arr_name, 0x00, sizeof(arr_name));

    DATA8583 upload[ISO8583_LENGH];
    memset(upload, 0x00, sizeof(upload));

    if (p_st_private->i_resp_remain_len == 0)
    {
        i_resp_len = __packet_len(p_data);
        p_st_private->i_resp_remain_len = i_resp_len + 2 - ui_data_len;

        p_st_private->p_resp_packet = bytebuff_creat();
        if (p_st_private->p_resp_packet == NULL)
            goto ERROR;
    }
    else
        p_st_private->i_resp_remain_len -= ui_data_len;
    p_packet = p_st_private->p_resp_packet;
    if (bytebuff_add(p_packet, p_data, ui_data_len) != FR_SUCC)
        goto ERROR;
    if (p_st_private->i_resp_remain_len < 0)
        goto ERROR;
    if (p_st_private->i_resp_remain_len > 0)
        return APM_L7_ANALYZE_TODO;

    /*
     2字节:字节长度
     5字节：TPDU
     6字节：报文头
     2字节：消息类型
     8字节：位图
     之后为各个域的域值
    */

    //arr_unuse存放前13字节无用信息
    if (bytebuff_get_bytes(p_packet, arr_unuse, 13) == FR_FAIL)
        goto ERROR;

    //上报消息类型
    if (bytebuff_get_bytes(p_packet, arr_message_type, 2) == FR_FAIL)
        goto ERROR;
    p_data_bcd = __hex_bcd(arr_message_type, 2);
    upload[0].data_value = p_data_bcd;

    //确定位图 arr_bit_map_16为十六进制位图
    if (((*(p_data+15)) & 0x80) != 0x80)
        i_bit = 8;
    else
        i_bit = 16;
    if (bytebuff_get_bytes(p_packet, arr_bit_map_16, i_bit) == FR_FAIL)
        goto ERROR;

    for (i_count=0; i_count<i_bit*8; i_count++)
    {
        i_tmp = i_count/8;
        i_bit_pos = i_count - i_tmp*8;
        //如果该域有值
        if ((arr_bit_map_16[i_tmp]&(0x80>>i_bit_pos)) != 0)
        {
            //判断该域长度是定长还是变长
            if (Tbl8583[i_count].variable_flag == 0)
            {
                //如果数据类型是BCD码,i_temp长度取半
                if (Tbl8583[i_count].datatyp == 1)
                {
                    i_temp = (Tbl8583[i_count].length + 1) / 2;
                    if (bytebuff_get_bytes(p_packet, arr_value, i_temp) == FR_FAIL)
                        goto ERROR;
                    p_data_bcd = __hex_bcd(arr_value, i_temp);
                    //如果长度是奇数，舍最后一位
                    if ((Tbl8583[i_count].length%2) == 1)
                        *(p_data_bcd+i_temp*2-1) = '\0';
                    upload[i_count+1].data_value = p_data_bcd;
                }
                //如果数据类型是ASCII码或2进制
                else
                {
                    upload[i_count+1].data_value = (char*)frmalloc(Tbl8583[i_count].length+1);
                    if (upload[i_count+1].data_value == NULL)
                        goto ERROR;
                    memset(upload[i_count+1].data_value, 0x00, Tbl8583[i_count].length+1);
                    if (bytebuff_get_bytes(p_packet, upload[i_count+1].data_value, Tbl8583[i_count].length) == FR_FAIL)
                        goto ERROR;
                }
            }
            else if (Tbl8583[i_count].variable_flag == 2)
            {
                //变长情况（前1个字节为长度），16进制长度存进arr_len
                if (bytebuff_get_bytes(p_packet, arr_len, 1) == FR_FAIL)
                    goto ERROR;
                i_lengh = ((arr_len[0] & 0xf0)>>4)*10 + (arr_len[0] & 0x0f);
                //如果数据类型是BCD码,i_temp长度取半
                if (Tbl8583[i_count].datatyp == 1)
                {
                    i_temp = (i_lengh + 1) / 2;
                    if (bytebuff_get_bytes(p_packet, arr_value, i_temp) == FR_FAIL)
                        goto ERROR;
                    p_data_bcd = __hex_bcd(arr_value, i_temp);
                    //如果变长长度是奇数，舍最后一位
                    if ((i_lengh%2) == 1)
                        *(p_data_bcd+i_temp*2-1) = '\0';
                    upload[i_count+1].data_value = p_data_bcd;
                }
                //如果数据类型是ASCII码或2进制
                else
                {
                    upload[i_count+1].data_value = (char*)frmalloc(i_lengh+1);
                    if (upload[i_count+1].data_value == NULL)
                        goto ERROR;
                    memset(upload[i_count+1].data_value, 0x00, i_lengh+1);
                    if (bytebuff_get_bytes(p_packet, upload[i_count+1].data_value, i_lengh) == FR_FAIL)
                        goto ERROR;
                }
            }
            else if (Tbl8583[i_count].variable_flag == 3)
            {
                //变长情况（前2个字节为长度）
                if (bytebuff_get_bytes(p_packet, arr_len, 2) == FR_FAIL)
                    goto ERROR;
                i_lengh = ((arr_len[0] & 0xf0)>>4)*1000 + (arr_len[0] & 0x0f)*100 + ((arr_len[1] & 0xf0)>>4)*10 + (arr_len[1] & 0x0f);
                //如果数据类型是BCD码,i_temp长度取半
                if (Tbl8583[i_count].datatyp == 1)
                {
                    i_temp = (i_lengh + 1) / 2;
                    if (bytebuff_get_bytes(p_packet, arr_value, i_temp) == FR_FAIL)
                        goto ERROR;
                    p_data_bcd = __hex_bcd(arr_value, i_temp);
                    //如果变长长度是奇数，舍最后一位
                    if ((i_lengh%2) == 1)
                        *(p_data_bcd+i_temp*2-1) = '\0';
                    upload[i_count+1].data_value = p_data_bcd;
                }
                //如果数据类型是ASCII码或2进制
                else
                {
                    upload[i_count+1].data_value = (char*)frmalloc(i_lengh+1);
                    if (upload[i_count+1].data_value == NULL)
                        goto ERROR;
                    memset(upload[i_count+1].data_value, 0x00, i_lengh+1);
                    if (bytebuff_get_bytes(p_packet, upload[i_count+1].data_value, i_lengh) == FR_FAIL)
                        goto ERROR;
                }
            }
            else
                goto ERROR;
        }
    }

    for (i_count=0; i_count<i_bit*8+1; i_count++)
    {
        if (upload[i_count].data_value != NULL)
        {
            if (i_count==0)
            {
                if (frreport_body_l7_add_str(p_st_body_data, ISO8583_RESP_MESSAGE_TYPE, upload[i_count].data_value) == FR_FAIL)
                    goto ERROR;
            }
            else if (i_count==52 || i_count==64 || i_count==123 ||i_count==128)
            {
                snprintf(arr_name, sizeof(arr_name), "%s%d", arr_name_1, i_count);
                if (frreport_body_l7_add_bin(p_st_body_data, arr_name, upload[i_count].data_value, 8) == FR_FAIL)
                    goto ERROR;
            }
            else
            {
                snprintf(arr_name, sizeof(arr_name), "%s%d", arr_name_1, i_count);
                if (frreport_body_l7_add_str(p_st_body_data, arr_name, upload[i_count].data_value) == FR_FAIL)
                    goto ERROR;
            }
        }
    }

    for (i_count=0; i_count<i_bit*8+1; i_count++)
    {
        if (upload[i_count].data_value)
        {
            frfree(upload[i_count].data_value);
            upload[i_count].data_value = NULL;
        }
    }

    return APM_L7_ANALYZE_SET_RESP(APM_L7_ANALYZE_SUCC);

ERROR:
    if (p_packet)
    {
        bytebuff_free(&p_packet);
        p_st_private->p_resp_packet = NULL;
    }
    for (i_count=0; i_count<ISO8583_LENGH; i_count++)
    {
        if (upload[i_count].data_value)
        {
            frfree(upload[i_count].data_value);
            upload[i_count].data_value = NULL;
        }
    }
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 8583的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败\n
 *         APM_L7_ANALYZE_TODO   数据不完整
 *
 * \note
 *
 */
FR_STATIC int __req_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_8583_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    Frreport_data *p_st_report_data = NULL;
    unsigned long ul_tmp = 0;

    if (p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_8583_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    //如果连续的两个request
    if (p_st_private->p_lst_comm)
        __ISO8583_session_reset((void *)(p_st_private));

    //创建数据链表
    if (p_st_private->p_st_body_data_req == NULL)
    {
        p_st_private->p_st_body_data_req = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_req == NULL)
            goto ERROR;

        if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_req, p_st_conn) == FR_FAIL)
            goto ERROR;

        //seq ++
        p_st_private->ul_seq = frct_seq_increase(p_st_conn);

        //st_request_time_first_byte
        p_st_l4_trans->st_request_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_request_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;
    }

    /* 请求的字节数 */
    p_st_l4_trans->l_request_bytes += p_st_packet->ui_payload_len;

    //req解析
    i_ret = __req_parse(p_st_packet->p_payload, p_st_packet->ui_payload_len, p_st_private, p_st_private->p_st_body_data_req, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
    {
        frreport_body_free(&p_st_private->p_st_body_data_req);
        return i_ret;
    }
    if (i_ret == APM_L7_ANALYZE_TODO)
        return i_ret;

    if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ID, p_st_private->ul_seq) == FR_FAIL)
        goto ERROR;

    //ResponseRequired
    if (frreport_body_l7_add_int(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_ISRESPREQUIRED, 1) == FR_FAIL)
        goto ERROR;

    //start time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_START_TIMESTAMP, &p_st_l4_trans->st_request_time_first_byte) == FR_FAIL)
        goto ERROR;

    //st_request_time
    p_st_l4_trans->st_request_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_request_time.tv_usec = p_st_packet->st_timestamp.tv_usec;

    ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time_first_byte), &(p_st_l4_trans->st_request_time));
    //send_time_us
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_SEND_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //request bytes
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_DATA_BYTES, p_st_l4_trans->l_request_bytes) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_req, APM_REPORT_KEY_REQ_END_TIMESTAMP, &p_st_l4_trans->st_request_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_REQ);
    if (p_st_report_data == NULL)
        goto ERROR;

    //拷贝相关链表
    p_st_private->p_lst_comm = FRREPORT_BODY_L7LIST_CLONE_COMM(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_comm == NULL)
        goto ERROR;
    p_st_private->p_lst_req = FRREPORT_BODY_L7LIST_CLONE_REQ(p_st_private->p_st_body_data_req);
    if (p_st_private->p_lst_req == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_req) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_req = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __ISO8583_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 8583的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败\n
 *         APM_L7_ANALYZE_TODO   数据不完整
 *
 * \note
 *
 */
FR_STATIC int __resp_data_analysis(Conntrack *p_st_conn
                                 , Apm_packet *p_st_packet
                                 , Frhash_header *p_st_hash_report
                                 , L7_session *p_st_session)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7session_8583_private *p_st_private = NULL;
    L4_transaction *p_st_l4_trans = NULL;
    unsigned long ul_tmp = 0;
    Frreport_data* p_st_report_data = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL || p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    p_st_private = (L7session_8583_private*)p_st_session->p_session_private;
    p_st_l4_trans = &(p_st_private->st_l4_trans);

    if (p_st_l4_trans->st_response_time_first_byte.tv_sec == 0 && p_st_l4_trans->st_response_time_first_byte.tv_usec == 0)
    {
        //创建数据链表
        p_st_private->p_st_body_data_resp = frreport_body_new_l7(p_st_conn);
        if (p_st_private->p_st_body_data_resp == NULL)
            goto ERROR;

        if (p_st_l4_trans->st_request_time_first_byte.tv_sec != 0)
        {
            FRREPORT_BODY_L7LIST_SET_REQ(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_req);
            FRREPORT_BODY_L7LIST_SET_COMM(p_st_private->p_st_body_data_resp, &p_st_private->p_lst_comm);
        }
        else
        {
            if (frreport_body_l7_add_connInfo(p_st_private->p_st_body_data_resp, p_st_conn) == FR_FAIL)
                goto ERROR;
        }

        p_st_l4_trans->st_response_time_first_byte.tv_sec = p_st_packet->st_timestamp.tv_sec;
        p_st_l4_trans->st_response_time_first_byte.tv_usec = p_st_packet->st_timestamp.tv_usec;

        //start time
        if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_START_TIMESTAMP, &p_st_l4_trans->st_response_time_first_byte) == FR_FAIL)
            goto ERROR;

        if (p_st_l4_trans->st_request_time.tv_sec != 0 || p_st_l4_trans->st_request_time.tv_usec != 0)
        {
            //server time
            ul_tmp = frtime_diff(&(p_st_l4_trans->st_request_time), &(p_st_l4_trans->st_response_time_first_byte));
            if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, ul_tmp) == FR_FAIL)
                goto ERROR;
        }
        else
        {
            if (frreport_body_l7_add_ulong(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_SERVER_TIME_US, 0) == FR_FAIL)
                goto ERROR;
        }
    }

    //st_response_time
    p_st_l4_trans->st_response_time.tv_sec = p_st_packet->st_timestamp.tv_sec;
    p_st_l4_trans->st_response_time.tv_usec = p_st_packet->st_timestamp.tv_usec;
    /* 请求的字节数 */
    p_st_l4_trans->l_response_bytes += p_st_packet->ui_payload_len;

    //resp解析
    i_ret = __resp_parse(p_st_packet->p_payload, p_st_packet->ui_payload_len, p_st_private, p_st_private->p_st_body_data_resp, p_st_conn);
    if (i_ret == APM_L7_ANALYZE_FAIL)
    {
        frreport_body_free(&p_st_private->p_st_body_data_req);
        return i_ret;
    }
    if (i_ret == APM_L7_ANALYZE_TODO)
        return i_ret;

    //数据上报
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DATA_BYTES, p_st_l4_trans->l_response_bytes) == FR_FAIL)
        goto ERROR;

    //down load time
    ul_tmp = frtime_diff(&(p_st_l4_trans->st_response_time_first_byte), &(p_st_l4_trans->st_response_time));
    if (frreport_body_l7_add_long(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_DOWNLOAD_TIME_US, ul_tmp) == FR_FAIL)
        goto ERROR;

    //end time
    if (frreport_body_l7_add_timeval(p_st_private->p_st_body_data_resp, APM_REPORT_KEY_RESP_END_TIMESTAMP, &p_st_l4_trans->st_response_time) == FR_FAIL)
        goto ERROR;

    p_st_report_data = frreport_data_l7_new(FRREPORT_TYPE_L7DATA_RESP);
    if (p_st_report_data == NULL)
        goto ERROR;

    if (frreport_data_add_body(p_st_report_data, p_st_private->p_st_body_data_resp) == FR_FAIL)
        goto ERROR;
    p_st_private->p_st_body_data_resp = NULL;

    if (frreport_data_hash(p_st_hash_report, p_st_report_data) == FR_FAIL)
        goto ERROR;
    p_st_report_data = NULL;

    __ISO8583_session_reset((void *)(p_st_private));

    return i_ret;

ERROR:
    if (p_st_report_data)
        frreport_data_free(&p_st_report_data);
    __ISO8583_session_reset((void *)(p_st_private));
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 8583的packet解析
 *
 * \param p_st_conn          (入力链接信息)
 * \param p_st_packet        (入力packet信息)
 * \param p_st_hash_report   (保存Frreport_data)
 * \param p_st_session       (私有数据)
 *
 * \return APM_L7_ANALYZE_SUCC   成功\n
 *         APM_L7_ANALYZE_FAIL   失败\n
 *         APM_L7_ANALYZE_TODO   数据不完整
 *
 * \note
 *
 */
int ISO8583_analysis(Conntrack *p_st_conn
                  , Apm_packet *p_st_packet
                  , Frhash_header *p_st_hash_report)
{
    int i_ret = APM_L7_ANALYZE_SUCC;
    L7_session *p_st_session = NULL;

    if (p_st_conn == NULL || p_st_packet == NULL
        || p_st_hash_report == NULL)
        return APM_L7_ANALYZE_FAIL;

    /* 到Conntrack中取得session信息 */
    p_st_session = frct_get_session(p_st_conn);
    if (p_st_session == NULL)
        return APM_L7_ANALYZE_FAIL;

    //fin syn 包  销毁私有数据
    if (p_st_packet->em_analyz_cmd == FRANALYZ_CMD_FIN || p_st_packet->em_analyz_cmd == FRANALYZ_CMD_SYN)
    {
        ISO8583_session_destroy((void *)(p_st_session->p_session_private));
        p_st_session->p_session_private = NULL;
        return APM_L7_ANALYZE_SUCC;
    }

    //p_session_private   分配内存
    if (p_st_session->p_session_private == NULL)
    {
        p_st_session->p_session_private = __8583_private_create();
        //内存分配失败
        if (p_st_session->p_session_private == NULL)
            return APM_L7_ANALYZE_FAIL;
    }

    //request
    if (p_st_packet->i_direction == FR_DIRECT_CLIENT2SRV)
    {
        i_ret = __req_data_analysis(p_st_conn,p_st_packet,p_st_hash_report,p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }
    else//response
    {
        i_ret = __resp_data_analysis(p_st_conn,p_st_packet,p_st_hash_report, p_st_session);
        if (i_ret == APM_L7_ANALYZE_FAIL)
            goto ERROR;

        return i_ret;
    }

ERROR:
    if (p_st_session->p_session_private)
        ISO8583_session_destroy(p_st_session->p_session_private);
    p_st_session->p_session_private = NULL;
    return APM_L7_ANALYZE_FAIL;
}

/*!
 * 私有信息销毁
 *
 * \param p_private_session  (8583的私有session数据)
 *
 * \return FR_SUCC   成功\n
 *
 * \note
 *
 */
int ISO8583_session_destroy(void *p_private_session)
{
    L7session_8583_private *p_st_private = (L7session_8583_private*)p_private_session;

    if (p_st_private)
    {
        if (p_st_private->p_st_body_data_req)
            frreport_body_free(&p_st_private->p_st_body_data_req);

        if (p_st_private->p_st_body_data_resp)
            frreport_body_free(&p_st_private->p_st_body_data_resp);

        if (p_st_private->p_lst_req)
            frreport_body_l7list_free(&p_st_private->p_lst_req);

        if (p_st_private->p_lst_comm)
            frreport_body_l7list_free(&p_st_private->p_lst_comm);

        if (p_st_private->p_req_packet)
            bytebuff_free(&(p_st_private->p_req_packet));

        if (p_st_private->p_resp_packet)
            bytebuff_free(&(p_st_private->p_resp_packet));

        frfree(p_st_private);
    }
    return FR_SUCC;
}
